Libraries
library(tidyverse) #The Data God
library(tidygeocoder) #Geocoding Addresses
library(sf) #Data that can be plotted in maps
library(maps) #Maps
library(leaflet) #Interactive Map Plotting
library(leaflegend) #Legend add-on for leaflet
library(osrm) #Routing between points
Read in markets
markets <-read.csv("data/SNAP Retailer Location data.csv")
str(markets)
## 'data.frame': 231 obs. of 16 variables:
## $ Record.ID : int 237488 245647 247122 282559 287134 288538 305041 317458 320013 320890 ...
## $ Store.Name : chr "GATE PETROLEUM 1445" "CVS Pharmacy 4629" "PUBLIX 1376" "Fast Track Foods 313" ...
## $ Store.Street.Address: chr "506 NW 13th St" "6025 SE US Highway 301" "4115 NW 16th Blvd" "101 Main Dr" ...
## $ Additonal.Address : chr "" "" "" "" ...
## $ City : chr "Gainesville" "Hawthorne" "Gainesville" "Interlachen" ...
## $ State : chr "FL" "FL" "FL" "FL" ...
## $ Zip.Code : int 32601 32640 32605 32148 32608 32666 32669 32669 32140 32653 ...
## $ Zip4 : int 4907 7316 3505 4378 2217 5301 3432 2805 2959 2084 ...
## $ County : chr "ALACHUA" "ALACHUA" "ALACHUA" "PUTNAM" ...
## $ Store.Type : chr "Convenience Store" "Other" "Supermarket" "Convenience Store" ...
## $ Latitude : num 29.7 29.6 29.7 29.7 29.6 ...
## $ Longitude : num -82.3 -82.1 -82.4 -81.9 -82.4 ...
## $ Incentive.Program : logi NA NA NA NA NA NA ...
## $ Grantee.Name : logi NA NA NA NA NA NA ...
## $ x : num -9165968 -9137853 -9171245 -9115660 -9171522 ...
## $ y : num 3459417 3452000 3461589 3460035 3454319 ...
markets$Store.Type <- as.factor(markets$Store.Type)
levels(markets$Store.Type) #Check market types
## [1] "Convenience Store" "Farmers and Markets" "Grocery Store"
## [4] "Other" "Specialty Store" "Super Store"
## [7] "Supermarket"
markets.sf <- st_as_sf(markets, coords = c("Longitude", "Latitude"), crs = st_crs(4326)) #Create SF Object
Shelters
shelters <- read.csv("data/FL508_CoC_Addresses.csv")
shelters.GV <- shelters %>%
filter(CoC == "Gainesville/Alachua, Putnam Counties CoC") #Filter Gainesville/Alachua, Putnam Counties
unique(shelters.GV$Organization.Name) # How many Shelters?
## [1] "Another Way"
## [2] "Family Promise Gainesville"
## [3] "Lee Conlee House"
## [4] "Peaceful Paths"
## [5] "Volunteers of America | SSVF Programs"
## [6] "Alachua County Coalition for the Homeless and Hungry"
## [7] "Alachua County Housing Authority"
## [8] "Alachua County Social Services"
## [9] "Catholic Charities | Putnam"
## [10] "CDS, Family & Behavioral Health Services, Inc"
## [11] "Gainesville Housing Authority"
## [12] "Meridian Behavioral Healthcare, Inc."
## [13] "St. Francis House"
## [14] "VETSPACE"
## [15] "Volunteers of America | GPD"
shelters.GV <- shelters.GV %>%
distinct(Organization.Name, .keep_all = T) #Remove duplicate names.
#Fix Missing Data
shelters.GV <- shelters.GV[-c(1),]
shelters.GV[2,16] <- "926 St. Johns Ave"
shelters.GV[2,17] <- "Palatka"
shelters.GV[3,16] <- "2100 NW 53rd Ave"
shelters.GV[3,17] <- "Gainesville"
shelters.GV[4,16] <- "1810 NW 6th St"
shelters.GV[11,16] <- "1405 NW 13th St"
shelters.GV[14,16] <- "2130 NW 31st Ave"
#Create Address column
shelters.GV <- shelters.GV %>%
mutate(address = paste(address1, city, state, zip, sep = ","))
Geocode Shelters
geo.shelters <- shelters.GV %>%
geocode(address = address, method = "osm")
## Passing 14 addresses to the Nominatim single address geocoder
## Query completed in: 14.6 seconds
geo.shelters.sf <- st_as_sf(geo.shelters, coords = c("long", 'lat'), na.fail = F)
Plot Shelters
leaflet(geo.shelters.sf) %>%
addProviderTiles("CartoDB.Positron") %>%
addAwesomeMarkers(data = geo.shelters.sf, popup = ~Organization.Name)
Bus Data
bus.stops <- read_sf("data/RTSBusStops_Spring2024", layer = "RTSBusStops_Fall2023")
bus.stops
## Simple feature collection with 1033 features and 37 fields
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: -82.49242 ymin: 29.60017 xmax: -82.26397 ymax: 29.71513
## Geodetic CRS: NAD83(2011)
## # A tibble: 1,033 × 38
## OBJECTID OBJECTID_1 BSID STOP_NAME DESCRIPTIO STREET CROSS_STRE LATITUDE
## <dbl> <dbl> <dbl> <chr> <chr> <chr> <chr> <dbl>
## 1 1 614 1 Rosa Parks D… Northboun… SE 3r… SE 3rd ST 29.6
## 2 2 1318 2 Hampton Inn … Westbound… SE 2n… SE 1st ST 29.7
## 3 3 505 3 SW 2nd Avenu… Westbound… SW 2n… SW 2nd ST 29.7
## 4 4 1136 4 The Continuum Westbound… SW 2n… SW 6th ST 29.7
## 5 5 1137 6 720 SW 2nd A… Westbound… SW 2n… SW 8th ST 29.7
## 6 6 1262 7 Infinity Hall Westbound… SW 2n… SW 10th ST 29.7
## 7 7 834 8 Courtyard Ap… Southboun… SW 12… SW 2nd AVE 29.6
## 8 8 1261 9 Campus USA C… Southboun… SW 12… SW 4th AVE 29.6
## 9 9 1150 10 Norman Hall Southboun… SW 12… SW 6th AVE 29.6
## 10 10 1176 12 Norman Field… Westbound… SW 8t… SW 12th ST 29.6
## # ℹ 1,023 more rows
## # ℹ 30 more variables: LONGITUDE <dbl>, INTERSECTI <chr>, NEARSIDE_F <chr>,
## # DIRECTION_ <chr>, ROAD_MAINT <chr>, Jurisdicti <chr>, PAIRED_STO <dbl>,
## # LAST_UPDAT <date>, ACTIVE_INA <chr>, DATE_DEACT <date>, PRE_1990 <chr>,
## # BUSLANE <chr>, SIGNALIZED <dbl>, SCHOOLZONE <dbl>, LANDING_PA <chr>,
## # curb <chr>, curbcut <chr>, SIDEWALK_W <chr>, WAITING_PA <chr>,
## # LEANING_WA <dbl>, NO_BENCHES <dbl>, NO_TRASHCA <dbl>, NO_SHELTER <dbl>, …
bus.stops <- bus.stops %>%
filter(!OBJECTID == "0") #Remove retired bus stops
bus.stops <- bus.stops %>%
st_transform('+proj=longlat +datum=WGS84') #Create SF obj with correct CRS for plotting
#Test Bus Plots
leaflet(data = bus.stops) %>%
addTiles() %>%
addCircleMarkers(data = bus.stops, popup = ~STOP_NAME, radius = 0.5, fillOpacity = 1, color = "black")
#Read in Bus Route data and change CRS
bus.routes <- st_read("data/RTSBusRoutes_Spring2024") %>%
st_transform('+proj=longlat +datum=WGS84')
## Reading layer `Spring2024_Weekday' from data source
## `/Users/rgarlitz/Documents/UF/SPRING 2024/PHC6791 - Data Visualization in the Health Sciences/Small Group Projects/PHC6791_Small_Group_Project/data/RTSBusRoutes_Spring2024'
## using driver `ESRI Shapefile'
## Simple feature collection with 78 features and 82 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: 2606132 ymin: 220363.5 xmax: 2678795 ymax: 266589.3
## Projected CRS: NAD83 / Florida North (ftUS)
head(bus.routes)
## Simple feature collection with 6 features and 82 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: -82.49252 ymin: 29.625 xmax: -82.27151 ymax: 29.67955
## Geodetic CRS: +proj=longlat +datum=WGS84
## OBJECTID_1 OBJECTID route_id shape_id last_updat agency_id route_shor
## 1 1 543 52 52O 07/07/2023 4030 52
## 2 2 544 52 52I 07/07/2023 4030 52
## 3 3 78 78 78O <NA> 4030 78
## 4 4 788 78 78I <NA> 4030 78
## 5 5 107 11 711O 02/05/2015 4030 711
## 6 6 127 126 126O 02/17/2015 4030 126
## route_long route_desc route_type
## 1 Uf Health - Jonesville <NA> 3
## 2 Jonesville - UF Health <NA> 3
## 3 78 - Butler Plaza to Santa Fe <NA> 3
## 4 78 - Butler Plaza to Santa Fe <NA> 3
## 5 Downtown Station - Eastwood Meadows <NA> 3
## 6 UF East/West Circulator (Lakeside - Sorority Row) <NA> 3
## start_time end_time avg_rider_ direction_ length_mi AM_freq Midday_fre
## 1 <NA> <NA> <NA> 0 12.400000 0 0
## 2 <NA> <NA> <NA> 1 11.700000 0 0
## 3 <NA> <NA> <NA> 0 0.000000 0 0
## 4 <NA> <NA> <NA> 0 0.000000 0 0
## 5 6:03 22:58 <NA> 0 7.986574 60 60
## 6 <NA> <NA> <NA> 0 3.143535 0 0
## PM_freq Night_freq span date_est cycle Colors Span_End RouteType State
## 1 0 0 <NA> <NA> 0 <NA> <NA> 4 2
## 2 0 0 <NA> <NA> 0 <NA> <NA> 4 2
## 3 0 0 <NA> <NA> 0 <NA> <NA> 0 0
## 4 0 0 <NA> <NA> 0 <NA> <NA> 0 0
## 5 60 60 <NA> Fall 2014 60 9E8A6C <NA> 0 1
## 6 0 0 <NA> Summer2015 0 7CC6F3 <NA> 0 1
## Saturday Sunday Summer Special Version Notes Weekdays YearBegan YearEnded
## 1 0 0 0 1 2 <NA> 1 2023 0
## 2 0 0 0 1 2 <NA> 1 2023 0
## 3 0 0 0 0 1 <NA> 1 0 0
## 4 0 0 0 0 1 <NA> 1 0 0
## 5 1 1 1 0 1 <NA> 1 0 0
## 6 1 1 1 0 5 <NA> 1 0 0
## SemesterBe SemesterEn DateBegan DateEnded Deviation last_reald Shape_Leng
## 1 8 0 2023-08-21 <NA> 0 2023-07-07 57032.132117
## 2 8 0 2023-08-21 <NA> 0 2023-07-07 60680.847624
## 3 0 0 <NA> <NA> 0 <NA> 8.671341
## 4 0 0 <NA> <NA> 0 <NA> 8.782329
## 5 0 0 <NA> <NA> 1 <NA> 0.000000
## 6 0 0 <NA> <NA> 0 <NA> 0.000000
## OBJECTID_2 Name Proposed cost_year date_date_
## 1 0 <NA> <NA> 0 <NA>
## 2 0 <NA> <NA> 0 <NA>
## 3 1 78 Butler Plaza - Santa Fe 1899-12-30 0 2022-08-15
## 4 2 78 Santa Fe - Butler Plaza 1899-12-30 0 2022-08-15
## 5 3 <NA> <NA> 0 2014-08-18
## 6 4 <NA> <NA> 0 2015-05-04
## time_date_ date_dat_2 time_dat_2 dir_id dir_name full_name hours_year
## 1 <NA> <NA> <NA> <NA> <NA> <NA> 0
## 2 <NA> <NA> <NA> <NA> <NA> <NA> 0
## 3 <NA> <NA> <NA> <NA> <NA> <NA> 0
## 4 <NA> <NA> <NA> <NA> <NA> <NA> 0
## 5 00:00:00.000 2015-05-03 00:00:00.000 <NA> <NA> <NA> 0
## 6 00:00:00.000 2016-08-14 00:00:00.000 <NA> <NA> <NA> 0
## date_last_ time_last_ line_id line_name map_id map_name maxheadway maxmph
## 1 <NA> <NA> <NA> <NA> <NA> <NA> 0 0
## 2 <NA> <NA> <NA> <NA> <NA> <NA> 0 0
## 3 <NA> <NA> <NA> <NA> <NA> <NA> 0 0
## 4 <NA> <NA> <NA> <NA> <NA> <NA> 0 0
## 5 2015-02-05 00:00:00.000 <NA> <NA> <NA> <NA> 0 0
## 6 2015-02-17 00:00:00.000 <NA> <NA> <NA> <NA> 0 0
## mi minheadway minmph objectid_3 objectid_4 objectid_5 pattern route_ty_2
## 1 0 0 0 0 0 0 <NA> 0
## 2 0 0 0 0 0 0 <NA> 0
## 3 0 0 0 0 0 0 <NA> 0
## 4 0 0 0 0 0 0 <NA> 0
## 5 0 0 0 9 9 0 <NA> 1
## 6 0 0 0 21 23 0 <NA> 2
## semester_b semester_e shape_le_1 shape_le_2 shape_le_3 url vehicle_co
## 1 0 0 0 0.00 0.00 <NA> 0
## 2 0 0 0 0.00 0.00 <NA> 0
## 3 0 0 0 0.00 0.00 <NA> 0
## 4 0 0 0 0.00 0.00 <NA> 0
## 5 8 1 0 42169.11 42169.11 <NA> 0
## 6 5 5 0 16597.87 16597.87 <NA> 0
## vehicle_ty year_began year_ended Shape_Le_4 Shape_Le_5
## 1 <NA> 0 0 0.00 65855.68
## 2 <NA> 0 0 0.00 61571.71
## 3 <NA> 2022 0 48203.71 48203.71
## 4 <NA> 2022 0 48569.35 48569.35
## 5 <NA> 2014 2015 40066.21 40066.21
## 6 <NA> 2015 2016 16597.87 16597.87
## geometry
## 1 LINESTRING (-82.34691 29.64...
## 2 LINESTRING (-82.49031 29.65...
## 3 LINESTRING (-82.38811 29.62...
## 4 LINESTRING (-82.43197 29.67...
## 5 LINESTRING (-82.3227 29.645...
## 6 LINESTRING (-82.33578 29.64...
#Test Plotting LINESTRING
plot(st_geometry(bus.routes))

#Plotting Route, Stop, and Market Data
leaflet(bus.routes) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolylines(data = bus.routes, opacity = 1, color = "purple", label = bus.routes$route_id, weight = 2) %>%
addCircleMarkers(data = bus.stops, popup = ~STOP_NAME, weight = 1, radius = 2, fillOpacity = 1) %>%
addCircleMarkers(data = markets.sf, popup = ~Store.Name, weight = 2, radius = 4, fillOpacity = 1, color = "red")
Change the Icons
#Create column of store names without spaces for Icons
markets.sf <- markets.sf %>%
mutate(Icons = case_when(
Store.Type == "Supermarket" ~ "Supermarket",
Store.Type == "Convenience Store" ~ "ConvenienceStore",
Store.Type == "Farmers and Markets" ~ "FarmersMarket",
Store.Type == "Grocery Store" ~ "Grocery",
Store.Type == "Super Store" ~ "SuperStore",
Store.Type == "Specialty Store" ~ "Specialty",
Store.Type == "Other" ~ "Other"
))
#Check number of Icons
markets.sf$Icons <- as.factor(markets.sf$Icons)
levels(markets.sf$Icons)
## [1] "ConvenienceStore" "FarmersMarket" "Grocery" "Other"
## [5] "Specialty" "Supermarket" "SuperStore"
#List of Icons for each store type
store.icons <- awesomeIconList(
Supermarket = makeAwesomeIcon(
icon = "shopping-cart",
markerColor = "lightred",
library= "fa"
),
ConvenienceStore = makeAwesomeIcon(
icon = "pizza",
iconColor = "black",
markerColor = "blue",
library = "ion"
),
FarmersMarket = makeAwesomeIcon(
icon = "group",
markerColor = "green",
library = "fa"
),
Grocery = makeAwesomeIcon(
icon = "shopping-basket",
markerColor = "pink",
library = "fa"
),
SuperStore = makeAwesomeIcon(
icon = "cubes",
markerColor = "purple",
library = "fa"
),
Specialty = makeAwesomeIcon(
icon = "info",
markerColor = "lightgray",
library = "fa"
),
Other = makeAwesomeIcon(
icon = "asterisk",
markerColor = "orange",
library = "fa"
)
)
shelter.icon <- makeAwesomeIcon(
icon = "home",
iconColor = "black",
markerColor = "red",
library = "fa"
)
#Add bus route colors
bus.route.colors <- colorFactor(c("#0D479C",
"#10D3DE",
"#04109A",
"#83D5FD",
"#7F1F4A",
"#6FE329",
"#50CBE7",
"#5A19A6",
"#641D60",
"#3529D6",
"#EF6DD0",
"#7A54BE",
"#B01ECC",
"#F2A5FA",
"#4BCE4A",
"#84F22B",
"#8B618C",
"#48C880",
"#5C4DAE",
"#AE0C0D",
"#FC0AF2",
"#4973A4",
"#B5EFC3",
"#749B5D",
"#03A747"), bus.routes$route_id)
Plot the Full Map
leaflet(markets.sf) %>%
addProviderTiles("CartoDB.Positron") %>%
addAwesomeMarkers(icon = ~store.icons[Icons],
label = ~as.character(Store.Name, Store.Type),
group = "Stores") %>% #EBT/SNAP Markets
addLegendAwesomeIcon(iconSet = store.icons,
title = "Store Types",
position = "topright",
group = "Stores") %>%
addAwesomeMarkers(data = geo.shelters.sf,
popup = paste0(
"<b>Organization: </b>",
geo.shelters.sf$Organization.Name,
"<br>",
"<b>Address: </b>",
geo.shelters.sf$address1
),
icon = shelter.icon, group = "Shelters") %>% #Shelters
addPolylines(data = bus.routes,
opacity = 1,
popup = paste0(
"<b>Route: </b>",
bus.routes$shape_id,
"<br>",
"<b>Line: </b>",
bus.routes$route_long
),
label = bus.routes$route_id,
weight = 3,
group = "Bus Routes", color = ~bus.route.colors(route_id)) %>% #Bus Routes
#addLegendFactor(pal = bus.route.colors, values = bus.routes$route_id, group = "Bus Routes", position = "bottomleft" , orientation = "horizontal") %>% #Legend for Bus Routes
addCircleMarkers(lng = bus.stops$LONGITUDE,
lat = bus.stops$LATITUDE,
popup = paste0(
"<b>Stop: </b>",
bus.stops$STOP_NAME,
"<br>",
"<b>Line: </b>",
bus.stops$DESCRIPTIO
),
radius = 4,
opacity = 1,
stroke = F,
fillOpacity = 1,
color = "darkgrey",
group = "Bus Stops") %>% #Bus Stops
addLayersControl(overlayGroups = c("Shelters","Stores","Bus Routes","Bus Stops"), position = "topleft", options = layersControlOptions(collapsed = F)) #Filter
Plotting Specific Routes
##Plotting specific routes between locations.
GRACE <- geo.shelters.sf[c(5),] #Grab shelter sf information for GRACE
walmart3877 <- markets.sf[c(82),] #Grab market sf information for particular store
#Create Route information
GRACE_walmart3877.route <- osrmRoute(dst = walmart3877, src = GRACE)
## Error in st_transform.sfc(st_geometry(x), crs, ...): cannot transform sfc object with missing crs
Line 25/26 Inbound/Outbound
#Plot Route 25/26 I/O
leaflet(data = markets.sf) %>%
addProviderTiles("CartoDB.Positron") %>%
#setView(lng = -82.30367, lat = 29.66646,zoom = 13) %>%
addAwesomeMarkers(data = markets.sf[c(22,63, 72, 82,124,139,143, 144,148, 180,196, 203, 227),], icon = ~store.icons[Icons],
popup = ~as.character(Store.Street.Address),
label = ~as.character(Store.Name),
group = "Stores") %>%
addAwesomeMarkers(data = GRACE,
popup = paste0(
"<b>Organization: </b>",
GRACE$Organization.Name,
"<br>",
"<b>Address: </b>",
GRACE$address1
),
icon = shelter.icon, group = "Shelters") %>%
#addPolylines(data = GRACE_walmart3877.route, color = "red") %>% #If you wanted to plot routes between points
addPolylines(data = bus.routes[c(75, 76),],
opacity = 1,
popup = paste0(
"<b>Route: </b>",
bus.routes[c(75, 76),]$shape_id,
"<br>",
"<b>Line: </b>",
bus.routes[c(75, 76),]$route_long
),
label = ~as.character(route_id),
weight = 3,
group = "Bus Routes", color = "#03A747") %>%
addPolylines(data = bus.routes[c(10,11),],
opacity = 1,
popup = paste0(
"<b>Route: </b>",
bus.routes[c(10,11),]$shape_id,
"<br>",
"<b>Line: </b>",
bus.routes[c(10,11),]$route_long
),
label = bus.routes[c(10,11),]$route_id,
weight = 3,
group = "Bus Routes", color = "#3529D6") %>%
addCircleMarkers(data = bus.stops[c(323, 892),],
popup = paste0(
"<b>Stop: </b>",
bus.stops[c(323, 892),]$STOP_NAME,
"<br>",
"<b>Line: </b>",
bus.stops[c(323, 892),]$DESCRIPTIO
),
radius = 4,
opacity = 1,
stroke = F,
fillOpacity = 1,
color = "darkred",
group = "Bus Stops")
Line 8/6 Inbound/Outbound
leaflet(data = markets.sf) %>%
addProviderTiles("CartoDB.Positron") %>%
#setView(lng = -82.30367, lat = 29.66646,zoom = 13) %>%
addAwesomeMarkers(data = markets.sf[c(10, 36,42,113,134,156,158,169,188,190, 194,195,196,198, 203,209, 212),], icon = ~store.icons[Icons],
popup = ~as.character(Store.Street.Address),
label = ~as.character(Store.Name),
group = "Stores") %>% #Plot markets along the route
addAwesomeMarkers(data = geo.shelters.sf[c(3,9,4,11, 12,1,14),],
popup = paste0(
"<b>Organization: </b>",
GRACE$Organization.Name,
"<br>",
"<b>Address: </b>",
GRACE$address1
),
icon = shelter.icon, group = "Shelters") %>% #Plot Shelters along the route
addPolylines(data = bus.routes[c(17,31),],
opacity = 1,
popup = paste0(
"<b>Route: </b>",
bus.routes[c(17,31),]$shape_id,
"<br>",
"<b>Line: </b>",
bus.routes[c(17,31),]$route_long
),
label = ~as.character(route_id),
weight = 3,
group = "Bus Routes", color = "#03A747") %>% #Plot line 8
addPolylines(data = bus.routes[c(19,49),],
opacity = 1,
popup = paste0(
"<b>Route: </b>",
bus.routes[c(19,49),]$shape_id,
"<br>",
"<b>Line: </b>",
bus.routes[c(19,49),]$route_long
),
label = bus.routes[c(19,49),]$route_id,
weight = 3,
group = "Bus Routes", color = "#3529D6") %>% #Plot line 6
addCircleMarkers(data = bus.stops[c(12),],
popup = paste0(
"<b>Stop: </b>",
bus.stops[c(12),]$STOP_NAME,
"<br>",
"<b>Line: </b>",
bus.stops[c(12),]$DESCRIPTIO
),
radius = 4,
opacity = 1,
stroke = F,
fillOpacity = 1,
color = "darkred",
group = "Bus Stops") #Plot UF Bus stops